package com.zl.ble.service;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.util.Log;

import com.zl.ble.BLEConstants;
import com.zl.ble.ReceiveListener;
import com.zl.ble.connect.ConnectedListener;
import com.zl.ble.connect.ConnectedThread;

import java.io.IOException;
import java.util.Arrays;
import java.util.UUID;

public class BluetoothService {
    private AcceptThread mAcceptThread;
    private ConnectedThread mConnectedThread;
    private int mState;
    private ReceiveListener mReceiveListener;
    private BluetoothSocket mBluetoothSocket;

    public BluetoothService() {
        reStart();
    }


    public synchronized void connected() {
        Log.d(BLEConstants.TAG, "connected");
        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }
        if (mAcceptThread != null) {
            mAcceptThread.cancel();
            mAcceptThread = null;
        }
        mConnectedThread = new ConnectedThread(mBluetoothSocket);
        mConnectedThread.setConnectedListener(mConnectedListener);
        mConnectedThread.start();
    }


    public void reStart() {
        Log.d(BLEConstants.TAG, "start");
        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }
        if (mAcceptThread == null) {
            mAcceptThread = new AcceptThread();
            mAcceptThread.start();
        }
        mState = BLEConstants.STATE_LISTEN;
    }

    public void stop() {
        Log.d(BLEConstants.TAG, "start");
        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }
        if (mAcceptThread != null) {
            mAcceptThread.cancel();
            mAcceptThread = null;
        }
        mState = BLEConstants.STATE_NONE;
    }


    private ConnectedListener mConnectedListener = new ConnectedListener() {

        @Override
        public void onReceive(byte[] msg) {
            Log.i(BLEConstants.TAG, "onReceive：" + Arrays.toString(msg));
            if (null != mReceiveListener && null != msg && msg.length > 0) {
                mReceiveListener.onReceive(msg);
                mReceiveListener.onReceiveLog(new String(msg));
            }
        }

        @Override
        public void onConnected() {

        }

        @Override
        public void onDisConnected(Exception e) {
            if (mState != BLEConstants.STATE_LISTEN) {
                reStart();
            }
        }
    };

    public void setReceiveListener(ReceiveListener mReceiveListener) {
        this.mReceiveListener = mReceiveListener;
    }


    public boolean write(byte[] message) {
        ConnectedThread r;
        synchronized (BluetoothService.this) {
            if (mState != BLEConstants.STATE_CONNECTED) return false;
            r = mConnectedThread;
        }
        if (r != null) {
            return r.write(message);
        }
        return false;
    }

    public int getState() {
        return mState;
    }

    public void setState(int mState) {
        this.mState = mState;
    }

    private class AcceptThread extends Thread {
        private final BluetoothServerSocket mmServerSocket;

        public AcceptThread() {
            BluetoothServerSocket tmp = null;
            try {
                tmp = BluetoothAdapter.getDefaultAdapter().listenUsingInsecureRfcommWithServiceRecord(BLEConstants.SERVICE_NAME, UUID.fromString(BLEConstants.SPP_UUID));
            } catch (IOException e) {
                e.printStackTrace();
            }
            mmServerSocket = tmp;
            mState = BLEConstants.STATE_LISTEN;
        }

        @Override
        public void run() {
            super.run();
            setName("SOCKET_LISTEN");
            while (mState != BLEConstants.STATE_CONNECTED) {
                try {
                    mBluetoothSocket = mmServerSocket.accept();
                } catch (IOException e) {
                    Log.e(BLEConstants.TAG, "accept() failed", e);
                    break;
                }
                if (mBluetoothSocket != null) {
                    synchronized (BluetoothService.this) {
                        switch (mState) {
                            case BLEConstants.STATE_LISTEN:
                            case BLEConstants.STATE_CONNECTING:
                                mState = BLEConstants.STATE_CONNECTED;
                                connected();
                                break;
                            case BLEConstants.STATE_NONE:
                            case BLEConstants.STATE_CONNECTED:
                                try {
                                    mBluetoothSocket.close();
                                } catch (IOException e) {
                                    Log.e(BLEConstants.TAG, "Could not close unwanted socket", e);
                                }
                                break;
                        }
                    }
                }
            }
            Log.i(BLEConstants.TAG, "END mAcceptThread");
        }

        public void cancel() {
            Log.d(BLEConstants.TAG, "cancel " + this);
            try {
                mmServerSocket.close();
            } catch (IOException e) {
                Log.e(BLEConstants.TAG, "close() of server failed", e);
            }
        }
    }
}
